#pragma once 

#include<iostream>
#include<queue>
#include<pthread.h>
#include"Task.hpp"

#define NUM 6

class ThreadPoll
{
    private:
        int num;
        bool stop;
        std::queue<Task> task_queue;
        pthread_mutex_t lock;
        pthread_cond_t cond;

        ThreadPoll(int _num = NUM):num(_num),stop(false)
        {
            pthread_mutex_init(&lock,nullptr);
            pthread_cond_init(&cond,nullptr);
        }

        ThreadPoll(const ThreadPoll&){}

        static ThreadPoll*single_instance;

    public:

        //线程池单例设计
        static ThreadPoll*getinstance()
        {
            static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
            if(single_instance == nullptr)
            {
                pthread_mutex_lock(&_mutex);
                if(single_instance == nullptr)
                {
                    //类内创建线程池并完成初始化
                    single_instance = new ThreadPoll();
                    single_instance->InitThreadPoll();
                }
                pthread_mutex_unlock(&_mutex);
            }
            return single_instance;
        }

        //判断线程是否退出
        bool IsStop()
        {
            return stop;
        }

        bool TaskQueueIsEmpty()
        {
            return task_queue.size()==0?true:false;
        }

        void Lock()
        {
            pthread_mutex_lock(&lock);
        }

        void Unlock()
        {
            pthread_mutex_unlock(&lock);
        }

        void ThreadWait()
        {
            //使用条件变量，条件变量满足时唤醒线程继续执行任务
             pthread_cond_wait(&cond,&lock);
        }

        void ThreadWakeup()
        {
            pthread_cond_signal(&cond);
        }

        static void *ThreadRoutine(void*args)
        {
            ThreadPoll*tp = (ThreadPoll*)args;
            
            while(true)
            {
                Task t;
                tp->Lock();
                //如果任务队列中没有任务，则让线程进行休眠;防止伪唤醒的出现，使用while循环
                while (tp->TaskQueueIsEmpty())
                {
                   tp->ThreadWait();
                }
                tp->PopTask(t);
                tp->Unlock();
                t.ProcessOn();
            }
        }

        bool InitThreadPoll()
        {
            for(int i =0;i<num;i++)
            {
                pthread_t tid;
                //线程从线程池中拿取任务执行，需要通过this指针
                if(pthread_create(&tid,nullptr,ThreadRoutine,this)!=0)
                {
                    LOG(FATAL,"create thread pool error ");
                    return false;
                }
            }
            LOG(INFO,"create thread pool success ");
            return true;
        }

        void PushTask(const Task&task)
        {
            Lock();
            task_queue.push(task);//将任务放到任务队列中
            Unlock();
            ThreadWakeup();
        }

        void PopTask(Task&task)
        {
            task = task_queue.front();
            task_queue.pop();
        }

        ~ThreadPoll()
        {
            pthread_mutex_destroy(&lock);
            pthread_cond_destroy(&cond);
        } 
};

 ThreadPoll*ThreadPoll::single_instance = nullptr;